package com.gopay.solution.manager.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.gopay.common.constants.cps.CpsConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.dao.solution.CpsAcctProdMastQueryDAO;
import com.gopay.common.domain.cps.CpsAcctProdMast;
import com.gopay.common.domain.cps.CpsProductLineInfo;
import com.gopay.common.exception.validator.GopayCheckException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.constants.solution.SolutionTypeConstant;
import com.gopay.solution.dao.SsPlSolutionRelDAO;
import com.gopay.solution.dao.smelly.CpsAcctProdMastTempDAO;
import com.gopay.solution.dao.smelly.CpsProductLineInfoTempDAO;
import com.gopay.solution.domain.po.SolutionMeta;
import com.gopay.solution.domain.po.SolutionRuleDtl;
import com.gopay.solution.domain.po.SsPlSolutionRel;
import com.gopay.solution.domain.po.SsProdLineTransDtl;
import com.gopay.solution.domain.po.SsProdLineTransSolution;
import com.gopay.solution.domain.vo.Solution;
import com.gopay.solution.manager.SolutionManager;
import com.gopay.solution.manager.SsPlSolutionManager;

/**
 * 产品线方案管理器
 * 
 * @SsPlSolutionManagerImpl.java
 * @author MA HUAN
 * @2013-4-11 下午4:27:07 www.gopay.com.cn Inc.All rights reserved.
 */

@Service(value="ssPlSolutionManager")
public class SsPlSolutionManagerImpl implements SsPlSolutionManager {
    
    @Resource(name = "cpsAcctProdMastQueryDAO")
    private CpsAcctProdMastQueryDAO cpsAcctProdMastQueryDAO;

    @Resource(name = "cpsProductLineInfoTempDAO")
    private CpsProductLineInfoTempDAO cpsProductLineInfoTempDAO;

    @Resource(name = "cpsAcctProdMastTempDAO")
    private CpsAcctProdMastTempDAO cpsAcctProdMastTempDAO;

    @Resource(name = "ssProdLineTransSoluManager")
    private SolutionManager ssProdLineTransSoluManager;

    @Resource(name = "ssPlSolutionRelDAO")
    private SsPlSolutionRelDAO ssPlSolutionRelDAO;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
    public void saveSsPlTranSolution(String prodLineName, List<String> acctProdIds, List<String> tranIds) throws GopayCheckException{

        // 保存产品线数据
        List<CpsProductLineInfo> existRecs = cpsProductLineInfoTempDAO.listByProdLineName(prodLineName);
        if(existRecs != null && existRecs.size() > 0) {
            throw new GopayCheckException(ProcCodeConstants.PROC_CODE_100E5013, "产品线名称重复");
        }
        CpsProductLineInfo prodLine = new CpsProductLineInfo();
        prodLine.setProdLineId(cpsProductLineInfoTempDAO.getProdLineId());
        prodLine.setProdLineName(prodLineName);
        prodLine.setProdLineDesc(prodLineName);
        prodLine.setDelFlag(0);
        prodLine.setCreatedTs(DateUtils.getSystemDate());
        prodLine.setLastUpdTs(DateUtils.getSystemDate());
        prodLine.setLastUpdTranCode("");
        cpsProductLineInfoTempDAO.save(prodLine);

        // 更新账户产品信息
        cpsAcctProdMastTempDAO.setProdLineIdForAcctProd(prodLine.getProdLineId(), acctProdIds);

        // 保存交易方案
        if (tranIds != null && tranIds.size() > 0) {
            SolutionMeta meta = new SsProdLineTransSolution();
            meta.setSolutionId(ssProdLineTransSoluManager.nextSolutionId());
            meta.setSolutionCode(1L);
            meta.setSolutionVersion(1L);
            meta.setSolutionName(prodLineName);
            meta.setSolutionDesc(prodLineName);
            meta.setCreateTime(DateUtils.getSystemDate());
            meta.setLastUpdTime(DateUtils.getSystemDate());
            meta.setLastUpdTranCode("");

            List<SolutionRuleDtl> rules = new ArrayList<SolutionRuleDtl>();
            for (String tranId : tranIds) {
                SsProdLineTransDtl rule = new SsProdLineTransDtl();
                rule.setSq(ssProdLineTransSoluManager.nextSolutionDtlId());
                rule.setSolutionId(meta.getSolutionId());
                rule.setGopayIntTxnCd(tranId);
                rule.setCreateTime(DateUtils.getSystemDate());
                rule.setLastUpdTime(DateUtils.getSystemDate());
                rule.setLastUpdTranCode("");

                rules.add(rule);
            }

            Solution solu = new Solution();
            solu.setMeta(meta);
            solu.setRuleDtls(rules);
            ssProdLineTransSoluManager.save(solu);
            
            
            // 保存产品线与方案关系,如果没有方案，则也无需保存这个关系，所以写在if块里面
            SsPlSolutionRel rel = new SsPlSolutionRel();
            rel.setProdLineId(prodLine.getProdLineId());
            rel.setSolutionId(solu.getMeta().getSolutionId());
            rel.setSolutionType(SolutionTypeConstant.TRANS_PRODLINE_TRANS);
            rel.setCreatedTs(DateUtils.getSystemDate());
            rel.setLastUpdTs(DateUtils.getSystemDate());
            rel.setLastUpdTranCode("");
            ssPlSolutionRelDAO.save(rel);
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
    public void editSsPlTranSolution(String prodLineId, String prodLineName, List<String> acctProdIds,
            List<String> tranIds) throws GopayCheckException {
        
        // 保存产品线数据
        List<CpsProductLineInfo> existRecs = cpsProductLineInfoTempDAO.listByProdLineName(prodLineName);
        if(existRecs != null && existRecs.size() > 0) {
            for(CpsProductLineInfo existRec : existRecs) {
                //假如同名列表中的ID与本次被修改的产品线ID不等，则说明为本产品线重新指定的产品线名称和已有产品线名称重复
                if(!existRec.getProdLineId().equals(prodLineId)) {
                    throw new GopayCheckException(ProcCodeConstants.PROC_CODE_100E5013, "产品线名称重复");
                }
            }
        }
        
        //更新产品线数据
        CpsProductLineInfo prodLine = cpsProductLineInfoTempDAO.find(CpsProductLineInfo.class, prodLineId);
        prodLine.setProdLineName(prodLineName);
        prodLine.setProdLineDesc(prodLineName);
        prodLine.setLastUpdTs(DateUtils.getSystemDate());
        prodLine.setLastUpdTranCode("");
        cpsProductLineInfoTempDAO.update(prodLine);

        // 更新账户产品信息: 
        //1.先将原有的账户产品的产品线ID设置为空
        List<CpsAcctProdMast> oldProdList = cpsAcctProdMastQueryDAO.findByProdLineId(prodLine.getProdLineId());
        if(oldProdList != null && oldProdList.size() > 0) {
            List<String> oldProdIdList = new ArrayList<String>();
            for(CpsAcctProdMast oldProd : oldProdList) {
                oldProdIdList.add(oldProd.getProdCode());
            }
            cpsAcctProdMastTempDAO.setProdLineIdForAcctProd(CpsConstants.DEFAULT_PRODLINE_ID, oldProdIdList);
        }
        //2.再将新设置的账户产品的产品线ID设置为当前的新产品线ID
        cpsAcctProdMastTempDAO.setProdLineIdForAcctProd(prodLine.getProdLineId(), acctProdIds);

        // 更新交易方案：
        //1. 根据产品线与方案关系表，获取方案ID
        SsPlSolutionRel rel = ssPlSolutionRelDAO.getByPlIdAndSoluType(prodLine.getProdLineId(), SolutionTypeConstant.TRANS_PRODLINE_TRANS);
        if(rel == null) {
            throw new GopayCheckException("","产品线可用方案配置错误");
        }
        //2. 根据方案ID获取方案信息
        Solution solu = ssProdLineTransSoluManager.load(rel.getSolutionId());
        //3. 更新方案元数据信息
        solu.getMeta().setSolutionName(prodLineName);
        solu.getMeta().setSolutionDesc(prodLineName);
        solu.getMeta().setLastUpdTime(DateUtils.getSystemDate());
        solu.getMeta().setLastUpdTranCode("");
        //4. 更新方案规则明细列表
        List<SolutionRuleDtl> rules = new ArrayList<SolutionRuleDtl>();
        if (tranIds != null && tranIds.size() > 0) {
            for (String tranId : tranIds) {
                SsProdLineTransDtl rule = new SsProdLineTransDtl();
                rule.setSq(ssProdLineTransSoluManager.nextSolutionDtlId());
                rule.setSolutionId(solu.getMeta().getSolutionId());
                rule.setGopayIntTxnCd(tranId);
                rule.setCreateTime(DateUtils.getSystemDate());
                rule.setLastUpdTime(DateUtils.getSystemDate());
                rule.setLastUpdTranCode("");

                rules.add(rule);
            }
        }
        solu.setRuleDtls(rules);
        
        //5. 刷新方案数据
        ssProdLineTransSoluManager.modify(solu);
    }

}
